package ge.telasi.tasks.fixture;

import ge.telasi.tasks.PersistenceUtils;
import ge.telasi.tasks.controller.TaskController;
import ge.telasi.tasks.model.FlowPermission;
import ge.telasi.tasks.model.Task;
import ge.telasi.tasks.model.User;
import java.util.HashMap;
import java.util.Map;
import javax.persistence.EntityManager;

import static ge.telasi.tasks.model.Task.*;
import static ge.telasi.tasks.model.FlowPermission.*;

/**
 * Create default FlowPermission configuration.
 *
 * @author dimitri
 */
public class FlowPermissionFixture extends Fixture<FlowPermission> {
    private static int[] NOT_CLOSED_STATUSES = {Task.STATUS_DRAFT, Task.STATUS_OPEN,
        Task.STATUS_PAUSED, Task.STATUS_COMPLETE_OK, Task.STATUS_COMPLETE_CANCEL
    };
    private static int[] ALL_STATUSES = {Task.STATUS_DRAFT, Task.STATUS_OPEN,
        Task.STATUS_PAUSED, Task.STATUS_COMPLETE_OK, Task.STATUS_COMPLETE_CANCEL,
        Task.STATUS_CLOSED_OK, Task.STATUS_CLOSED_CANCEL
    };
    private static int[] ALL_STATUSES_WITHOUT_DRAFT = {Task.STATUS_OPEN,
        Task.STATUS_PAUSED, Task.STATUS_COMPLETE_OK, Task.STATUS_COMPLETE_CANCEL,
        Task.STATUS_CLOSED_OK, Task.STATUS_CLOSED_CANCEL
    };
    private static int[] NOT_CLOSED_STATUSES_WITHOUT_DRAFT = {Task.STATUS_OPEN,
        Task.STATUS_PAUSED, Task.STATUS_COMPLETE_OK, Task.STATUS_COMPLETE_CANCEL
    };

    private User user;

    @Override
    protected Map<String, FlowPermission> execute(EntityManager em) {
//        user = new UserFixture().getEntity(em, UserFixture.ADMIN);
        user = em.find(User.class, 3);
        System.out.println(user.getUsername());

        // ================ General task ================

        // **** Subject, priority and receivers
        createPermission(em, TYPE_GENERAL, ROLE_OWNER, OPERATION_CHANGE_SUBJECT, NOT_CLOSED_STATUSES_WITHOUT_DRAFT);
        createPermission(em, TYPE_GENERAL, ROLE_OWNER, OPERATION_CHANGE_PRIORITY, NOT_CLOSED_STATUSES_WITHOUT_DRAFT);
        createPermission(em, TYPE_GENERAL, ROLE_OWNER, OPERATION_CHANGE_RECEIVERS, NOT_CLOSED_STATUSES_WITHOUT_DRAFT);

        // ================ Attachemnts ===================

        createPermission(em, TYPE_GENERAL, ROLE_OWNER, OPERATION_ADD_ATTACHMENT, NOT_CLOSED_STATUSES);
        createPermission(em, TYPE_GENERAL, ROLE_ASSIGNEE, OPERATION_ADD_ATTACHMENT, NOT_CLOSED_STATUSES_WITHOUT_DRAFT);
        createPermission(em, TYPE_GENERAL, ROLE_CARBON_COPY, OPERATION_ADD_ATTACHMENT, NOT_CLOSED_STATUSES_WITHOUT_DRAFT);
        createPermission(em, TYPE_GENERAL, ROLE_PREPARED_BY, OPERATION_ADD_ATTACHMENT, STATUS_DRAFT);

        createPermission(em, TYPE_GENERAL, ROLE_OWNER, OPERATION_REMOVE_ATTACHMENT, NOT_CLOSED_STATUSES);
        createPermission(em, TYPE_GENERAL, ROLE_FILE_OWNER, OPERATION_REMOVE_ATTACHMENT, NOT_CLOSED_STATUSES);

        createPermission(em, TYPE_GENERAL, ROLE_OWNER, OPERATION_DOWNLOAD_ATTACHMENT, ALL_STATUSES);
        createPermission(em, TYPE_GENERAL, ROLE_ASSIGNEE, OPERATION_DOWNLOAD_ATTACHMENT, ALL_STATUSES_WITHOUT_DRAFT);
        createPermission(em, TYPE_GENERAL, ROLE_CARBON_COPY, OPERATION_DOWNLOAD_ATTACHMENT, ALL_STATUSES_WITHOUT_DRAFT);
        createPermission(em, TYPE_GENERAL, ROLE_FILE_OWNER, OPERATION_DOWNLOAD_ATTACHMENT, ALL_STATUSES);
        createPermission(em, TYPE_GENERAL, ROLE_PREPARED_BY, OPERATION_DOWNLOAD_ATTACHMENT, STATUS_DRAFT);

        // ================ Statuses =====================

        // draft -> (*)

        createPermission(em, TYPE_GENERAL, ROLE_OWNER, OPERATION_CHANGE_STATUS, STATUS_DRAFT, STATUS_OPEN);
        createPermission(em, TYPE_GENERAL, ROLE_OWNER, OPERATION_CHANGE_STATUS, STATUS_DRAFT, STATUS_DRAFT);
        createPermission(em, TYPE_GENERAL, ROLE_PREPARED_BY, OPERATION_CHANGE_STATUS, STATUS_DRAFT, STATUS_DRAFT);

        // open -> (*)
        
        createPermission(em, TYPE_GENERAL, ROLE_OWNER, OPERATION_CHANGE_STATUS, STATUS_OPEN, STATUS_OPEN);
        createPermission(em, TYPE_GENERAL, ROLE_OWNER, OPERATION_CHANGE_STATUS, STATUS_OPEN, STATUS_PAUSED);
        createPermission(em, TYPE_GENERAL, ROLE_OWNER, OPERATION_CHANGE_STATUS, STATUS_OPEN, STATUS_CLOSED_OK);
        createPermission(em, TYPE_GENERAL, ROLE_OWNER, OPERATION_CHANGE_STATUS, STATUS_OPEN, STATUS_CLOSED_CANCEL);

        createPermission(em, TYPE_GENERAL, ROLE_ASSIGNEE, OPERATION_CHANGE_STATUS, STATUS_OPEN, STATUS_OPEN);
        createPermission(em, TYPE_GENERAL, ROLE_ASSIGNEE, OPERATION_CHANGE_STATUS, STATUS_OPEN, STATUS_COMPLETE_OK);
        createPermission(em, TYPE_GENERAL, ROLE_ASSIGNEE, OPERATION_CHANGE_STATUS, STATUS_OPEN, STATUS_COMPLETE_CANCEL);

        createPermission(em, TYPE_GENERAL, ROLE_CARBON_COPY, OPERATION_CHANGE_STATUS, STATUS_OPEN, STATUS_OPEN);

        // paused -> (*)

        createPermission(em, TYPE_GENERAL, ROLE_OWNER, OPERATION_CHANGE_STATUS, STATUS_PAUSED, STATUS_PAUSED);
        createPermission(em, TYPE_GENERAL, ROLE_OWNER, OPERATION_CHANGE_STATUS, STATUS_PAUSED, STATUS_OPEN);
        createPermission(em, TYPE_GENERAL, ROLE_OWNER, OPERATION_CHANGE_STATUS, STATUS_PAUSED, STATUS_CLOSED_OK);
        createPermission(em, TYPE_GENERAL, ROLE_OWNER, OPERATION_CHANGE_STATUS, STATUS_PAUSED, STATUS_CLOSED_CANCEL);

        createPermission(em, TYPE_GENERAL, ROLE_ASSIGNEE, OPERATION_CHANGE_STATUS, STATUS_PAUSED, STATUS_PAUSED);
        
        createPermission(em, TYPE_GENERAL, ROLE_CARBON_COPY, OPERATION_CHANGE_STATUS, STATUS_PAUSED, STATUS_PAUSED);

        // complete -> (*)

        createPermission(em, TYPE_GENERAL, ROLE_OWNER, OPERATION_CHANGE_STATUS, STATUS_COMPLETE_OK, STATUS_COMPLETE_OK);
        createPermission(em, TYPE_GENERAL, ROLE_OWNER, OPERATION_CHANGE_STATUS, STATUS_COMPLETE_OK, STATUS_OPEN);
        createPermission(em, TYPE_GENERAL, ROLE_OWNER, OPERATION_CHANGE_STATUS, STATUS_COMPLETE_OK, STATUS_PAUSED);
        createPermission(em, TYPE_GENERAL, ROLE_OWNER, OPERATION_CHANGE_STATUS, STATUS_COMPLETE_OK, STATUS_CLOSED_OK);
        createPermission(em, TYPE_GENERAL, ROLE_OWNER, OPERATION_CHANGE_STATUS, STATUS_COMPLETE_OK, STATUS_CLOSED_CANCEL);

        createPermission(em, TYPE_GENERAL, ROLE_OWNER, OPERATION_CHANGE_STATUS, STATUS_COMPLETE_CANCEL, STATUS_COMPLETE_CANCEL);
        createPermission(em, TYPE_GENERAL, ROLE_OWNER, OPERATION_CHANGE_STATUS, STATUS_COMPLETE_CANCEL, STATUS_OPEN);
        createPermission(em, TYPE_GENERAL, ROLE_OWNER, OPERATION_CHANGE_STATUS, STATUS_COMPLETE_CANCEL, STATUS_PAUSED);
        createPermission(em, TYPE_GENERAL, ROLE_OWNER, OPERATION_CHANGE_STATUS, STATUS_COMPLETE_CANCEL, STATUS_CLOSED_OK);
        createPermission(em, TYPE_GENERAL, ROLE_OWNER, OPERATION_CHANGE_STATUS, STATUS_COMPLETE_CANCEL, STATUS_CLOSED_CANCEL);

        createPermission(em, TYPE_GENERAL, ROLE_ASSIGNEE, OPERATION_CHANGE_STATUS, STATUS_COMPLETE_OK, STATUS_COMPLETE_OK);
        createPermission(em, TYPE_GENERAL, ROLE_ASSIGNEE, OPERATION_CHANGE_STATUS, STATUS_COMPLETE_OK, STATUS_COMPLETE_CANCEL);
        createPermission(em, TYPE_GENERAL, ROLE_ASSIGNEE, OPERATION_CHANGE_STATUS, STATUS_COMPLETE_OK, STATUS_OPEN);

        createPermission(em, TYPE_GENERAL, ROLE_ASSIGNEE, OPERATION_CHANGE_STATUS, STATUS_COMPLETE_CANCEL, STATUS_COMPLETE_OK);
        createPermission(em, TYPE_GENERAL, ROLE_ASSIGNEE, OPERATION_CHANGE_STATUS, STATUS_COMPLETE_CANCEL, STATUS_COMPLETE_CANCEL);
        createPermission(em, TYPE_GENERAL, ROLE_ASSIGNEE, OPERATION_CHANGE_STATUS, STATUS_COMPLETE_CANCEL, STATUS_OPEN);

        createPermission(em, TYPE_GENERAL, ROLE_CARBON_COPY, OPERATION_CHANGE_STATUS, STATUS_COMPLETE_OK, STATUS_COMPLETE_OK);
        createPermission(em, TYPE_GENERAL, ROLE_CARBON_COPY, OPERATION_CHANGE_STATUS, STATUS_COMPLETE_CANCEL, STATUS_COMPLETE_CANCEL);

        // closed -> (*)

        createPermission(em, TYPE_GENERAL, ROLE_OWNER, OPERATION_CHANGE_STATUS, STATUS_CLOSED_OK, STATUS_CLOSED_OK);
        createPermission(em, TYPE_GENERAL, ROLE_OWNER, OPERATION_CHANGE_STATUS, STATUS_CLOSED_OK, STATUS_CLOSED_CANCEL);
        createPermission(em, TYPE_GENERAL, ROLE_OWNER, OPERATION_CHANGE_STATUS, STATUS_CLOSED_OK, STATUS_OPEN);
        createPermission(em, TYPE_GENERAL, ROLE_OWNER, OPERATION_CHANGE_STATUS, STATUS_CLOSED_OK, STATUS_PAUSED);

        createPermission(em, TYPE_GENERAL, ROLE_OWNER, OPERATION_CHANGE_STATUS, STATUS_CLOSED_CANCEL, STATUS_CLOSED_OK);
        createPermission(em, TYPE_GENERAL, ROLE_OWNER, OPERATION_CHANGE_STATUS, STATUS_CLOSED_CANCEL, STATUS_CLOSED_CANCEL);
        createPermission(em, TYPE_GENERAL, ROLE_OWNER, OPERATION_CHANGE_STATUS, STATUS_CLOSED_CANCEL, STATUS_OPEN);
        createPermission(em, TYPE_GENERAL, ROLE_OWNER, OPERATION_CHANGE_STATUS, STATUS_CLOSED_CANCEL, STATUS_PAUSED);

        // ================ Delete Task =====================

        createPermission(em, TYPE_GENERAL, ROLE_PREPARED_BY, OPERATION_DELETE_TASK, STATUS_DRAFT);
        createPermission(em, TYPE_GENERAL, ROLE_OWNER, OPERATION_DELETE_TASK, STATUS_DRAFT);
        createPermission(em, TYPE_GENERAL, ROLE_OWNER, OPERATION_DELETE_TASK, STATUS_OPEN);

        // ================ Add/Remove Parent ================

        createPermission(em, TYPE_GENERAL, ROLE_OWNER, OPERATION_ADD_PARENT, NOT_CLOSED_STATUSES);
        createPermission(em, TYPE_GENERAL, ROLE_OWNER, OPERATION_REMOVE_PARENT, NOT_CLOSED_STATUSES);

        // empty map!
        return new HashMap<String, FlowPermission>();
    }

    public void createPermission(EntityManager em,
            int taskType, String role,
            int operation, int taskStatus
    ) {
        createPermission(em, taskType, role, operation, taskStatus, null);
    }

    public void createPermission(EntityManager em,
            int taskType, String role,
            int operation, int[] scope
    ) {
        for (int status : scope) {
            createPermission(em, taskType, role, operation, status, null);
        }
    }

    public void createPermission(EntityManager em,
            int taskType, String role, int operation,
            int taskStatus, Integer finalStatus
    ) {
        FlowPermission perm = new FlowPermission();
        perm.setTaskStatus(taskStatus);
        perm.setFinalStatus(finalStatus);
        perm.setOperation(operation);
        perm.setRole(role);
        perm.setTaskType(taskType);
        PersistenceUtils.beginTransaction(em);
        perm = new TaskController().createPermission(em, user, perm);
        PersistenceUtils.endTransaction(em);
    }

}
